home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1994 March / Internet Info CD-ROM (Walnut Creek) (March 1994).iso / networking / ip / ka9q / src890906.arc / PKTDRVR.C < prev    next >
C/C++ Source or Header  |  1989-09-07  |  10KB  |  399 lines

  1. /* Driver for FTP Software's packet driver interface */
  2. #include <stdio.h>
  3. #include <dos.h>
  4. #include "global.h"
  5. #include "proc.h"
  6. #include "mbuf.h"
  7. #include "enet.h"
  8. #include "ax25.h"
  9. #include "slip.h"
  10. #include "kiss.h"
  11. #include "iface.h"
  12. #include "ec.h"
  13. #include "timer.h"
  14. #include "arp.h"
  15. #include "trace.h"
  16. #include "pktdrvr.h"
  17. #include "config.h"
  18.  
  19. static int access_type __ARGS((int intno,int if_class,int if_type,int if_number,
  20.     char *type,unsigned typelen,INTERRUPT (*receiver) __ARGS((void)) ));
  21. static int driver_info __ARGS((int intno,int handle,int *version,
  22.     int *class,int *type,int *number,int *basic));
  23. static int release_type __ARGS((int intno,int handle));
  24. static int get_address __ARGS((int intno,int handle,char *buf,int len));
  25. static int pk_raw __ARGS((struct iface *iface,struct mbuf *bp));
  26. static int pk_stop __ARGS((struct iface *iface));
  27. static int send_pkt __ARGS((int intno,char *buffer,unsigned length));
  28.  
  29.  
  30. static INTERRUPT (*Pkvec[])() = { pkvec0,pkvec1,pkvec2 };
  31. static struct pktdrvr Pktdrvr[PK_MAX];
  32. static unsigned int Npk;
  33. static int Derr;
  34.  
  35. /* Send raw packet (caller provides header) */
  36. static int
  37. pk_raw(iface,bp)
  38. struct iface *iface;    /* Pointer to interface control block */
  39. struct mbuf *bp;    /* Data field */
  40. {
  41.     register struct pktdrvr *pp;
  42.     int16 size;
  43.     struct mbuf *bp1;
  44.  
  45.     pp = &Pktdrvr[iface->dev];
  46.     size = len_mbuf(bp);
  47.  
  48.     switch(pp->class){
  49.     case CL_ETHERNET:
  50.         dump(iface,IF_TRACE_OUT,TYPE_ETHER,bp);
  51.         if(size < 60)
  52.             size = 60;
  53.         break;
  54.     case CL_SERIAL_LINE:
  55.         dump(iface,IF_TRACE_OUT,TYPE_IP,bp);
  56.         break;
  57.     case CL_AX25:
  58.         dump(iface,IF_TRACE_OUT,TYPE_AX25,bp);
  59.         break;
  60.     case CL_KISS:
  61.         dump(iface,IF_TRACE_OUT,TYPE_AX25,bp);
  62.         /* This *really* shouldn't be done here, but it was the
  63.          * easiest way. Put the type field for KISS TNC on front.
  64.          */
  65.         if((bp1 = pushdown(bp,1)) == NULLBUF){
  66.             free_p(bp);
  67.             return -1;
  68.         }
  69.         bp = bp1;
  70.         bp->data[0] = KISS_DATA;
  71.         break;
  72.     }
  73.     if(bp->next != NULLBUF){
  74.         /* Copy to contiguous buffer, since driver can't handle mbufs */
  75.         bp1 = copy_p(bp,size);
  76.         free_p(bp);
  77.         bp = bp1;
  78.         if(bp == NULLBUF)
  79.             return -1;
  80.     } else
  81.         bp->cnt = size;    /* Make sure packet size is big enough */
  82.  
  83.     send_pkt(pp->intno,bp->data,bp->cnt);
  84.     free_p(bp);
  85.     return 0;
  86. }
  87.  
  88. /* Packet driver receive routine. Called from an assembler hook that pushes
  89.  * the caller's registers on the stack so we can access and modify them.
  90.  * This is a rare example of call-by-location in C.
  91.  */
  92. void
  93. pkint(dev,di,si,bp,dx,cx,bx,ax,ds,es)
  94. unsigned short dev,di,si,bp,dx,cx,bx,ax,ds,es;
  95. {
  96.     register struct pktdrvr *pp;
  97.     struct phdr *phdr;
  98.  
  99.     if(dev >= Npk)
  100.         return;    /* Unknown packet */
  101.     pp = &Pktdrvr[dev];
  102.  
  103.     switch(ax){
  104.     case 0:    /* Space allocate call */
  105.         if((pp->buffer = alloc_mbuf(cx+sizeof(struct phdr))) != NULLBUF){
  106.             es = FP_SEG(pp->buffer->data);
  107.             di = FP_OFF(pp->buffer->data+sizeof(struct phdr));
  108.             pp->buffer->cnt = cx + sizeof(struct phdr);
  109.             phdr = (struct phdr *)pp->buffer->data;
  110.             phdr->iface = pp->iface;
  111.             switch(pp->class){
  112.             case CL_ETHERNET:
  113.                 phdr->type = TYPE_ETHER;
  114.                 break;
  115.             case CL_SERIAL_LINE:
  116.                 phdr->type = TYPE_IP;
  117.                 break;
  118.             case CL_AX25:
  119.                 phdr->type = TYPE_AX25;
  120.                 break;
  121.             case CL_KISS:
  122.                 phdr->type = TYPE_KISS;
  123.                 break;
  124.             }
  125.         } else {
  126.             es = di = 0;
  127.         }
  128.         break;
  129.     case 1:    /* Packet complete call */
  130.         enqueue(&Hopper,pp->buffer);
  131.         pp->buffer = NULLBUF;
  132.         break;
  133.     default:
  134.         break;
  135.     }
  136. }
  137.  
  138. /* Shut down the packet interface */
  139. static int
  140. pk_stop(iface)
  141. struct iface *iface;
  142. {
  143.     struct pktdrvr *pp;
  144.  
  145.     pp = &Pktdrvr[iface->dev];
  146.     /* Call driver's release_type() entry */
  147.     if(release_type(pp->intno,pp->handle1) == -1)
  148.         printf("%s: release_type error code %u\n",iface->name,Derr);
  149.  
  150.     if(pp->class == CL_ETHERNET)
  151.         release_type(pp->intno,pp->handle2);
  152.     return 0;
  153. }
  154. /* Attach a packet driver to the system
  155.  * argv[0]: hardware type, must be "packet"
  156.  * argv[1]: software interrupt vector, e.g., x7e
  157.  * argv[2]: interface label, e.g., "trw0"
  158.  * argv[3]: maximum number of packets allowed on transmit queue, e.g., "5"
  159.  * argv[4]: maximum transmission unit, bytes, e.g., "1500"
  160.  */
  161. int
  162. pk_attach(argc,argv,p)
  163. int argc;
  164. char *argv[];
  165. void *p;
  166. {
  167.     register struct iface *if_pk;
  168.     int class,type;
  169.     unsigned int intno;
  170.     static char iptype[] = {IP_TYPE >> 8,IP_TYPE};
  171.     static char arptype[] = {ARP_TYPE >> 8,ARP_TYPE};
  172.     long drvvec;
  173.     char sig[8];    /* Copy of driver signature "PKT DRVR" */
  174.     register struct pktdrvr *pp;
  175.  
  176.     if(Npk >= PK_MAX){
  177.         printf("Too many packet drivers\n");
  178.         return -1;
  179.     }
  180.     if(if_lookup(argv[2]) != NULLIF){
  181.         printf("Interface %s already exists\n",argv[2]);
  182.         return -1;
  183.     }
  184.  
  185.     intno = htoi(argv[1]);
  186.     /* Verify that there's really a packet driver there, so we don't
  187.      * go off into the ozone (if there's any left)
  188.      */
  189.     drvvec = (long)getvect(intno);
  190.     movblock(FP_OFF(drvvec)+3, FP_SEG(drvvec),
  191.         FP_OFF(sig),FP_SEG(sig),strlen(PKT_SIG));
  192.     if(strncmp(sig,PKT_SIG,strlen(PKT_SIG)) != 0){
  193.         printf("No packet driver loaded at int 0x%x\n",intno);
  194.         return -1;
  195.     }
  196.     if((if_pk = (struct iface *)calloc(1,sizeof(struct iface))) == NULLIF
  197.      ||(if_pk->name = strdup(argv[2])) == NULLCHAR){
  198.         free((char *)if_pk);
  199.         printf("pk_attach: no memory!\n");
  200.         return -1;
  201.     }
  202.     pp = &Pktdrvr[Npk];
  203.     if_pk->mtu = atoi(argv[4]);
  204.     if_pk->dev = Npk++;
  205.     if_pk->raw = pk_raw;
  206.     if_pk->stop = pk_stop;
  207.     pp->intno = intno;
  208.     pp->iface = if_pk;
  209.  
  210.      /* Version 1.08 of the packet driver spec dropped the handle
  211.       * requirement from the driver_info call.  However, if we are using
  212.       * a version 1.05 packet driver, the following call will fail.
  213.        */
  214.      if(driver_info(intno,-1,NULL,&class,&type,NULL,NULL) < 0){
  215.         /* Find out by exhaustive search what class this driver is (ugh) */
  216.         for(class=0;class<9;class++){
  217.             pp->handle1 = access_type(intno,class,ANYTYPE,0,iptype,2,
  218.                 Pkvec[if_pk->dev]);
  219.             if(pp->handle1 != -1 || Derr == TYPE_INUSE)
  220.                 break;
  221.         }
  222.         /* Now that we know, release it and do it all over again with the
  223.          * right type fields
  224.          */
  225.         release_type(intno,pp->handle1);
  226.     }
  227.     switch(class){
  228.     case CL_ETHERNET:
  229.         pp->handle1 = access_type(intno,class,ANYTYPE,0,iptype,2,
  230.             Pkvec[if_pk->dev]);
  231.         pp->handle2 = access_type(intno,class,ANYTYPE,0,arptype,2,
  232.             Pkvec[if_pk->dev]);            
  233.         if_pk->send = enet_send;
  234.         if_pk->output = enet_output;
  235.         /* Get hardware Ethernet address from driver */
  236.         if((if_pk->hwaddr = malloc(EADDR_LEN)) == NULLCHAR){
  237.             free(if_pk->name);
  238.             free((char *)if_pk);
  239.             printf("pk_attach: no memory!\n");
  240.             return -1;
  241.         }
  242.         get_address(intno,pp->handle1,if_pk->hwaddr,EADDR_LEN);
  243.         arp_init(ARP_ETHER,EADDR_LEN,IP_TYPE,ARP_TYPE,1,Ether_bdcst,pether,gether);
  244.         break;
  245. #ifdef    SLIP
  246.     case CL_SERIAL_LINE:
  247.         pp->handle1 = access_type(intno,class,ANYTYPE,0,NULLCHAR,0,
  248.          Pkvec[if_pk->dev]);
  249.         if_pk->send = slip_send;
  250.         break;
  251. #endif
  252. #ifdef    KISS
  253.     case CL_KISS:    /* Note that the raw routine puts on the command */
  254.         pp->handle1 = access_type(intno,class,ANYTYPE,0,NULLCHAR,0,
  255.          Pkvec[if_pk->dev]);
  256.         if_pk->send = ax_send;
  257.         if_pk->output = ax_output;
  258.         break;
  259. #endif
  260. #ifdef    AX25
  261.     case CL_AX25:
  262.         pp->handle1 = access_type(intno,class,ANYTYPE,0,NULLCHAR,0,
  263.          Pkvec[if_pk->dev]);
  264.         if_pk->send = ax_send;
  265.         if_pk->output = ax_output;
  266.         break;
  267. #endif
  268.     default:
  269.         printf("Packet driver has unsupported class %u\n",class);
  270.         free(if_pk->name);
  271.         free((char *)if_pk);
  272.         Npk--;
  273.         return -1;
  274.     }
  275.     pp->class = class;
  276.     if_pk->next = Ifaces;
  277.     Ifaces = if_pk;
  278.  
  279.     return 0;
  280. }
  281. static int
  282. access_type(intno,if_class,if_type,if_number,type,typelen,receiver)
  283. int intno;
  284. int if_class;
  285. int if_type;
  286. int if_number;
  287. char *type;
  288. unsigned typelen;
  289. INTERRUPT (*receiver)();
  290. {
  291.     union REGS regs;
  292.     struct SREGS sregs;
  293.  
  294.     segread(&sregs);
  295.     regs.h.dl = if_number;        /* Number */
  296.     sregs.ds = FP_SEG(type);    /* Packet type template */
  297.     regs.x.si = FP_OFF(type);
  298.     regs.x.cx = typelen;        /* Length of type */
  299.     sregs.es = FP_SEG(receiver);    /* Address of receive handler */
  300.     regs.x.di = FP_OFF(receiver);
  301.     regs.x.bx = if_type;        /* Type */
  302.     regs.h.ah = ACCESS_TYPE;    /* Access_type() function */
  303.     regs.h.al = if_class;        /* Class */
  304.     int86x(intno,®s,®s,&sregs);
  305.     if(regs.x.cflag){
  306.         Derr = regs.h.dh;
  307.         return -1;
  308.     } else
  309.         return regs.x.ax;
  310. }
  311. static int
  312. release_type(intno,handle)
  313. int intno;
  314. int handle;
  315. {
  316.     union REGS regs;
  317.  
  318.     regs.x.bx = handle;
  319.     regs.h.ah = RELEASE_TYPE;
  320.     int86(intno,®s,®s);
  321.     if(regs.x.cflag){
  322.         Derr = regs.h.dh;
  323.         return -1;
  324.     } else
  325.         return 0;
  326. }
  327. static int
  328. send_pkt(intno,buffer,length)
  329. int intno;
  330. char *buffer;
  331. unsigned length;
  332. {
  333.     union REGS regs;
  334.     struct SREGS sregs;
  335.  
  336.     segread(&sregs);
  337.     sregs.ds = FP_SEG(buffer);
  338.     regs.x.si = FP_OFF(buffer);
  339.     regs.x.cx = length;
  340.     regs.h.ah = SEND_PKT;
  341.     int86x(intno,®s,®s,&sregs);
  342.     if(regs.x.cflag){
  343.         Derr = regs.h.dh;
  344.         return -1;
  345.     } else
  346.         return 0;
  347. }
  348. static int
  349. driver_info(intno,handle,version,class,type,number,basic)
  350. int intno;
  351. int handle;
  352. int *version,*class,*type,*number,*basic;
  353. {
  354.     union REGS regs;
  355.  
  356.     regs.x.bx = handle;
  357.     regs.h.ah = DRIVER_INFO;
  358.     regs.h.al = 0xff;
  359.     int86(intno,®s,®s);
  360.     if(regs.x.cflag){
  361.         Derr = regs.h.dh;
  362.         return -1;
  363.     }
  364.     if(version != NULL)
  365.         *version = regs.x.bx;
  366.     if(class != NULL)
  367.         *class = regs.h.ch;
  368.     if(type != NULL)
  369.         *type = regs.x.dx;
  370.     if(number != NULL)
  371.         *number = regs.h.cl;
  372.     if(basic != NULL)
  373.         *basic = regs.h.al;
  374.     return 0;
  375. }
  376. static int
  377. get_address(intno,handle,buf,len)
  378. int intno;
  379. int handle;
  380. char *buf;
  381. int len;
  382. {
  383.     union REGS regs;
  384.     struct SREGS sregs;
  385.  
  386.     segread(&sregs);
  387.     sregs.es = FP_SEG(buf);
  388.     regs.x.di = FP_OFF(buf);
  389.     regs.x.cx = len;
  390.     regs.x.bx = handle;
  391.     regs.h.ah = GET_ADDRESS;
  392.     int86x(intno,®s,®s,&sregs);
  393.     if(regs.x.cflag){
  394.         Derr = regs.h.dh;
  395.         return -1;
  396.     }
  397.     return 0;
  398. }
  399.